﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IntelligentDecisioning.SharePoint.BusinessEntities;
using IntelligentDecisioning.SharePoint.Shared;
using Microsoft.SharePoint;
using Microsoft.Practices.SPG.Common.Logging;
using Microsoft.Practices.SPG.Common.ServiceLocation;
using IntelligentDecisioning.SharePoint.Definition;

namespace IntelligentDecisioning.SharePoint.repositories
{
    public class ListItemRepository<T> : IListItemRepository<T>, IDisposable where T : ListItemEntityBase, new()
    {
        #region Data 

        protected IDSharePointContext _context;
        protected ILogger _logger;
        protected SPSite _targetSite; 
        protected SPWeb _targetWeb;
        protected String _listName;
        protected String _logCategory = "ListRepository";
        private bool _isInitialised;
 
   
        #endregion

        #region Constructor

        public ListItemRepository()
        {
            _isInitialised = false;
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            try
            {
                if (_targetSite != null) _targetSite.Dispose();
            }
            catch { }

            try
            {
                if (_targetWeb != null) _targetWeb.Dispose();
            }
            catch 
            { }
        }

        #endregion

        #region GetList

        protected virtual SharePointList GetList()
        {
            return new SharePointList(_listName);
        }

        #endregion

        #region IListItemRepository Members

        #region Initialise Repository

        public void InitialiseRepository(String listName, IDSharePointContext context)
        {
            _listName = listName;
            _context = context;
            // SPG is configured to provide a ULS logging implementation by default
            _logger = SharePointServiceLocator.Current.GetInstance<ILogger>();

            _logger.LogDiagnostic(String.Format("Initialising {0} repository for sharepoint site {1}, use root web = {2},  target web url = {3}",
                                                   _listName,
                                                   context.SiteCollectionUrl,
                                                   context.UseRootWeb.ToString(),
                                                   context.WebRelativeURL),
                                      _logCategory);

            _targetSite = new SPSite(context.SiteCollectionUrl);
            _targetWeb = (context.UseRootWeb) ? _targetSite.OpenWeb() : _targetSite.OpenWeb(context.WebRelativeURL);
            _isInitialised = true;
        }

        #endregion

        #region Get Entity methods

        public List<T> GetEntities(SPQuery query, SPView view)
        {   
            if (_isInitialised)
            {
                SharePointList list = GetList();
                return list.GetItems<T>(_targetSite, _targetWeb, query, view);
            }
            else
            {
                throw new Exception("The List repository cannot be used until it is initialised. Ensure that InitialiseRepository has been called");
            }
        }

        public List<T> GetEntities()
        {
            return GetEntities(null, null);
        }

        public List<T> GetEntities(SPQuery query)
        {
            return GetEntities(query, null);
        }

        public List<T> GetEntities(SPView view)
        {
            return GetEntities(null, view);
        }
      

        public T GetEntity(SPQuery query)
        {
            List<T> entities = GetEntities(query, null);
            return (entities.Count > 0) ? entities[0] : null;
        }

        #endregion

        #region Add Entity Methods

        public T AddEntity(T entity)
        {
            if (_isInitialised)
            {
                SharePointList list = GetList();
                return list.AddItem<T>(_targetSite, _targetWeb, entity);
            }
            else
            {
                throw new Exception("The List repository cannot be used until it is initialised. Ensure that InitialiseRepository has been called");
            }
        }

        public List<T> AddEntities(List<T> entities)
        {
            // there is obviously a more efficient way to right this but lets see how this goes first

            List<T> entitiesAdded = new List<T>();
            foreach (T entity in entities)
            {
                entitiesAdded.Add(AddEntity(entity));
            }
            return entitiesAdded;
        }

        #endregion

        #region Delete entity methods

        public void DeleteEntities()
        {
            throw new NotImplementedException();
        }

        public void DeleteEntity(T item)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region Update entity methods

        public List<T> UpdateEntities(List<ListItemEntityBase> entities)
        {
            List<T> updatedEntities = new List<T>();

            foreach (T entity in entities)
            {
                updatedEntities.Add(UpdateEntity(entity));
            }

            return updatedEntities;
        }

        public T UpdateEntity(T entity)
        {
            throw new NotImplementedException();
        }

        #endregion

        #endregion
    }
}
